﻿using System;
using System.Text;
using System.Diagnostics;
using System.Collections.Generic;

namespace EpisodeWizard.Core
{

	/// <summary>
	/// Holds a string and its phonetics representation
	/// </summary>
	public class FuzzyString
	{

		/// <summary>
		/// Percentage of similarties between 2 strings
		/// </summary>
		public enum Resemblance
		{
			Identical	= 100,
			Similar		= 85,
			Different	= 70
		}


		/// <summary>
		/// The string data
		/// </summary>
		private string mData;
		public string Data
		{
			get
			{
				return mData;
			}
			set
			{
				mData = value;
				mStrippedData = Strip(mData);
			}
		}

		/// <summary>
		/// Data stripped for fuzzy comparison
		/// </summary>
		private string mStrippedData;

		/// <summary>
		/// Creates a fuzzy string
		/// </summary>
		/// <param name="_str"></param>
		public FuzzyString(string _str)
		{
			Data = _str;
		}

		/// <summary>
		/// Compares two strings
		/// Returns a value between 0 and 100, 100 meaning they are identical
		/// </summary>
		public int Compare(FuzzyString Other)
		{
			//return Levenshtein.LD(this.mData, Other.mData);

			if (mStrippedData == Other.mStrippedData)
			{
				return (int) Resemblance.Identical;
			}
			else
			{
				float Distance = FuzzyString.DistanceSift3(this.mStrippedData, Other.mStrippedData, 4);
				//float Distance2 = FuzzyStringCache.GetCachedDistance(this.mStrippedData, Other.mStrippedData, 4);

				float PropDiff = Math.Min(Distance / this.mStrippedData.Length, 1);
				return (int)(100 - PropDiff * 100);
			}
		}

		/// <summary>
		/// Removes parasite words and character for string comparison
		/// </summary>
		private string Strip(string str)
		{
			str = str.ToLower();

			if (str.StartsWith("a "))
			{
				str = str.Substring(2);
			}
			else if (str.StartsWith("the "))
			{
				str = str.Substring(4);
			}

			str = str.Replace(".", " ").Replace("'", " ").Replace("-", " ").Replace("_", " ").Replace("&", "and");
			//str = str.Replace(" and ", "").Replace(" ", "");
			str.Trim();

			return str;
		}

		public static float DistanceSift3(string s1, string s2, int maxOffset)
		{
			if (String.IsNullOrEmpty(s1))
				return
					String.IsNullOrEmpty(s2) ? 0 : s2.Length;
			if (String.IsNullOrEmpty(s2))
				return s1.Length;
			int c = 0;
			int offset1 = 0;
			int offset2 = 0;
			int lcs = 0;
			while ((c + offset1 < s1.Length)
				   && (c + offset2 < s2.Length))
			{
				if (s1[c + offset1] == s2[c + offset2]) lcs++;
				else
				{
					offset1 = 0;
					offset2 = 0;
					for (int i = 0; i < maxOffset; i++)
					{
						if ((c + i < s1.Length)
							&& (s1[c + i] == s2[c]))
						{
							offset1 = i;
							break;
						}
						if ((c + i < s2.Length)
							&& (s1[c] == s2[c + i]))
						{
							offset2 = i;
							break;
						}
					}
				}
				c++;
			}
			return (s1.Length + s2.Length) / 2 - lcs;
		}

		//private Resemblance DifferenceMetaphones(Metaphone.DoubleMetaphone meta1, Metaphone.DoubleMetaphone meta2)
		//{
		//    if (meta1.PrimaryKey == meta2.PrimaryKey)
		//    {
		//        return Resemblance.VerySimilar;
		//    }
		//    else
		//    {
		//        if (meta2.AlternateKey != null)
		//        {
		//            if (meta1.PrimaryKey == meta2.AlternateKey)
		//            {
		//                return Resemblance.Similar;
		//            }
		//        }
		//        if (meta1.AlternateKey != null)
		//        {
		//            if (meta2.PrimaryKey == meta1.AlternateKey)
		//            {
		//                return Resemblance.Similar;
		//            }
		//        }
		//    }
		//    return Resemblance.Different;
		//}

	}
}
